#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "assert.h"

#include "BList.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"





char *FeatureTerm::getTokenNOOS(char *s,int *type,int *pos)
{
	char tmp[256],*token;
	int i=0;
	char c;
	bool end=false;
	int state;

	*type=-1;

	state=0;

	while(!end) {
		c=s[(*pos)];
		(*pos)++;

		if (c!=0) {
			switch(state) {
			case -2: /* block comment: */ 
				if (c=='|') {
					c=s[(*pos)];
					(*pos)++;
					if (c=='#') state=0;
				} /* if */ 
				break;
			case -1: /* comment */ 
				if (c=='\r' || c=='\n') state=0;
				break;
			case 0:
				if (c==';') {
					state=-1;
				} else if (c=='#') {
					c=s[(*pos)];
					(*pos)++;
					if (c=='|') {
						state=-2;
					} else {
						*type=-1;
						return 0;
					} /* if */ 
				} else if (c=='>') {
					tmp[i++]=c;
					c=s[(*pos)];
					(*pos)++;
					if (c=='>') {
						tmp[i++]=c;
						*type=TOKEN_ROOT;
					} /* if */ 
					end=true;
				} else if (c=='.') {
					*type=TOKEN_PARENT;
					tmp[i++];
					do {
						c=s[(*pos)];
						(*pos)++;
						if (c=='.') tmp[i++]=c;
					}while(c=='.');
					(*pos)--;
					end=true;
				} else if (c=='?') {
					*type=TOKEN_INIT_VARIABLE;
					state=4;				
				} else if (c=='!') {
					*type=TOKEN_REF_VARIABLE;
					state=4;				

				} else if (c=='(' || c==')') {
					tmp[i++]=c;
					if (c=='(') *type=0;
						   else *type=1;
					end=true;
				} else if (c=='\"') {
					state=3;
				} else if ((c>='0' && c<='9') || c=='-') {
					tmp[i++]=c;
					*type=3;
					state=2;
				} else if (c!=' ' && c!='\r' && c!='\n' && c!='\t') {
					tmp[i++]=c;
					state=1;
				} /* if */ 
				break;
			case 1:
				if (c!=' ' && c!='\r' && c!='\n' && c!='\t' && 
					c!='(' && c!=')' && c!='\"') {
					tmp[i++]=c;
				} else {
					(*pos)--;
					*type=2;
					end=true;
				} /* if */ 
				break;
			case 2:
				if ((c>='0' && c<='9') || c=='.') {
					tmp[i++]=c;
					if (c=='.') *type=5;
				} else {
					(*pos)--;
					end=true;
				} /* if */ 
				break;
			case 3:
				if (c!='"') {
					tmp[i++]=c;
				} else {
					*type=4;
					end=true;
				} /* if */ 
				break;
			case 4:
				if (c!=' ' && c!='\r' && c!='\n' && c!='\t' && 
					c!='(' && c!=')' && c!='\"') {
					tmp[i++]=c;
				} else {
					(*pos)--;
					end=true;
				} /* if */ 
				break;
			} /* switch */ 
		} else {
			if (*type==-1 && state==1) *type=2;
			end=true;
		} /* if */ 
	} /* while */ 

	tmp[i]=0;
	if (strlen(tmp)==0 && *type!=4) {
		if (*type==TOKEN_REF_VARIABLE) {
			*type=TOKEN_SINGLETON;
			return 0;
		} else {			
			*type=-1;
			return 0;
		} // if 
	} /* if */ 

	token=new char[strlen(tmp)+1];
	strcpy(token,tmp);
	if (*type!=4) strlwr(token);

	return token;
} /* FeatureTerm::getTokenNOOS */ 


FeatureTerm *FeatureTerm::fromStringNOOS(char *s,FTKBase *m,Ontology *o)
{
	int pos=0;
	int type=0;
	char *token=0;

	FeatureTerm *f1=new FeatureTerm();
	pos=f1->fromStringNOOS_nonstatic(s,m,o);
	
	if (f1->m_ft==0) {
		delete f1;
		f1=0;
	} else {
		// Check that there are no more tokens:
		token=getTokenNOOS(s,&type,&pos);

		if (token!=0) {
			delete []token;
			delete f1;
			f1=0;
		} // if 
	} // if 
	return f1;
} /* FeatureTerm::fromStringNOOS */ 


int FeatureTerm::fromStringNOOS_nonstatic(char *s,FTKBase *m,Ontology *o)
{
	int pos=0;
	int type=0;
	char *token=0;
	FeatureTerm *f;

	token=getTokenNOOS(s,&type,&pos);
	switch(type) {
	case TOKEN_LEFT_PAR:
						delete []token;
						token=getTokenNOOS(s,&type,&pos);
						if (type==2 && (strcmp(token,"define")==0 || strcmp(token,"define-episode")==0)) {

							List<FeatureTerm> hierarchy;
							List<NOOSPathRecord> nprl;
							List<NOOSVariableRecord> nvl;
							List<NOOSVariableLinkRecord> nvll;
							List<FeatureTerm> specials;

							delete []token;
							f=fromStringNOOSInternal(s,m,o,o->get_sort("any"),&pos,&hierarchy,&nprl,&nvl,&nvll,&specials);

							if (f!=0) {
								/* process nprl list: */ 
								NOOSPathRecord *npr;
								List<FeatureTerm> *lf;
								FeatureTerm *f2;
								while(!nprl.EmptyP()) {
									npr=nprl.ExtractIni();
									if (npr->root!=0 && npr->p!=0) {
										lf=npr->root->readPath(npr->p);
										if (lf!=0 && lf->Length()==1) {
											f2=lf->ExtractIni();
											delete lf;
											if (f2!=0 && npr->f!=0) {
												if (npr->feature==0 && npr->f->isSet()) {
													npr->f->addSetValue(new FeatureTerm(f2));
												} else if (npr->feature!=0 && npr->f->isFeatureTerm()) {
													FeatureTerm *f3;
													f3=npr->f->featureValue(npr->feature);
													if (f3!=0) {
														if (f3->isSet()) {
															f3->addSetValue(new FeatureTerm(f2));
															delete f3;
														} else {
															FeatureTerm *f4;
															f4=FeatureTerm::SetFeatureTerm();

															f4->addSetValue(f3);
															f4->addSetValue(new FeatureTerm(f2));
															npr->f->removeFeatureValue(npr->feature);
															if (!npr->f->defineFeatureValueSecure(npr->feature,f4)) {
																printf("NOOS parser(1): wrong feature in sort! setting %s in %s\n",npr->feature->get(),npr->f->getSort()->get());
															} // if  
														} /* if */ 
													} else {
														if (!npr->f->defineFeatureValueSecure(npr->feature,new FeatureTerm(f2))) {
															printf("NOOS parser(2): wrong feature in sort! setting %s in %s\n",npr->feature->get(),npr->f->getSort()->get());
														} // if 
													} /* if */ 
												} /* if */ 
											} /* if */ 	
											delete f2;
										} else {
											if (lf!=0) {
												delete lf;
											} /* if */ 
										} /* if */ 
									} /* if */ 
									delete npr;
								} /* while */ 	
						
								/* process nvll list: */ 
								NOOSVariableRecord *vr,*vrtmp;
								NOOSVariableLinkRecord *vl;
								while(!nvll.EmptyP()) {
									vl=nvll.ExtractIni();
//									printf("Variable: %s\n",vl->variable->get());
									if (vl->f!=0 && vl->variable!=0) {
										vr=0;
										nvl.Rewind();
										while(vr==0 && nvl.Iterate(vrtmp)) {
											if (vrtmp->variable->cmp(vl->variable)) vr=vrtmp;
										} /* while */ 

										if (vr!=0) {
											if (vl->feature==0 && vl->f->isSet()) {
												vl->f->addSetValue(new FeatureTerm(vr->f));
											} else if (vl->feature!=0 && !vl->f->isSet()) {
												if (!vl->f->defineFeatureValueSecure(vl->feature,new FeatureTerm(vr->f))) {
													printf("NOOS parser(3): wrong feature in sort! setting %s in %s\n",vl->feature->get(),vl->f->getSort()->get());
												} // if 
											} /* if */ 
										} /* if */ 

									} /* if */ 
									delete vl;
								} /* while */ 

								/* process specials: */ 
								{
									List<Symbol> names;
									List<FeatureTerm> values;
									FeatureTerm *f_s;

									while(!specials.EmptyP()) {
										f_s=specials.ExtractIni();
									
										while(!f_s->m_ft->m_value.m_ft.m_feature_name->EmptyP()) names.Add(f_s->m_ft->m_value.m_ft.m_feature_name->ExtractIni());
										while(!f_s->m_ft->m_value.m_ft.m_feature_value->EmptyP()) values.Add(f_s->m_ft->m_value.m_ft.m_feature_value->ExtractIni());
										delete f_s->m_ft->m_value.m_ft.m_feature_name;
										delete f_s->m_ft->m_value.m_ft.m_feature_value;
										f_s->m_ft->m_value.m_ft.m_feature_name=0;
										f_s->m_ft->m_value.m_ft.m_feature_value=0;

										f_s->m_ft->m_value.m_special=f_s->getSort()->createSpecial(&names,&values);
										f_s->m_ft->m_data_type=DATATYPE_SPECIAL;
									} // while 
								}
								assign(f);
								delete f;
							} /* if */ 
							
							return pos;

						} else {
							delete []token;
							return -1;
						} /* if */ 
						break;
	case TOKEN_SYMBOL:
						{
							FeatureTerm *f;
							List<FeatureTerm> *l;
							Symbol *n=new Symbol(token);
							delete []token;

							l=m->SearchFT(n);
							if (l->Length()==1) {
								f=l->operator [](0);
								delete n;
								while(!l->EmptyP()) l->ExtractIni();
								delete l;

								assign(f);
								return pos;
							} else {
								if (l->Length()==0) {
									/* Create a new term of the appopiate sort and add it to the memory & undefined term list: */ 
									while(!l->EmptyP()) l->ExtractIni();
									delete l;								

									f=new FeatureTerm(n,o->get_sort("any"),0);
									m->AddUndefinedFT(f);

									assign(f);
									return pos;
								} else {
									while(!l->EmptyP()) l->ExtractIni();
									delete l;
									return -1;
								} /* if */ 
							} /* if */ 
						}

					  break;
	case TOKEN_INTEGER:{
							FeatureTerm *res=new FeatureTerm((Symbol *)0,atoi(token),o);
							delete []token;

							assign(res);
							delete res;
							return pos;
					   }
					   break;
	case TOKEN_FLOAT:  {
							FeatureTerm *res=new FeatureTerm((Symbol *)0,(float)atof(token),o);
							delete []token;

							assign(res);
							delete res;
							return pos;
					   }
					   break;
	case TOKEN_STRING: {
							FeatureTerm *res=new FeatureTerm((char *)0,token,o);
							delete []token;

							assign(res);
							delete res;
							return pos;
					   }
					   break;
	default:
			delete []token;
			return -1;
	} /* switch */ 
} /* FeatureTerm::fromStringNOOS_nonstatic */ 





FeatureTerm *FeatureTerm::fromStringNOOSInternal(char *s,FTKBase *m,Ontology *o,Sort *vsort,int *pos,List<FeatureTerm> *hierarchy,List<NOOSPathRecord> *nprl,List<NOOSVariableRecord> *nvl,List<NOOSVariableLinkRecord> *nvll,List<FeatureTerm> *specials)
{
	char *token=0;
	int type=0;
	Sort *sort=0;
	Symbol *name=0;
	Symbol *fname=0;
	FeatureTerm *fvalue=0;
	bool end=false;
	FeatureTerm *f=0;
	bool variable=false;
	char *variablename;
	bool feature_variable=false;
	char *feature_variablename;

	variablename=new char[256];
	feature_variablename=new char[256];

	/* Sort and name: */ 
	token=getTokenNOOS(s,&type,pos);

	if (type==TOKEN_INIT_VARIABLE) {
		variable=true;
		strcpy(variablename,token);
		delete []token;
		token=getTokenNOOS(s,&type,pos);
	} /* if */ 

	delete []token;
	if (type!=TOKEN_LEFT_PAR) {
		delete []variablename;
		delete []feature_variablename;
		return 0;
	} /* if */ 
	
	token=getTokenNOOS(s,&type,pos);
	if (type!=TOKEN_SYMBOL) {
		delete []variablename;
		delete []feature_variablename;
		return 0;
	} /* if */ 
	if (strcmp(token,"set")==0) {
		sort=0;
	} else {
		sort=o->get_sort(token);
	} /* if */ 
	delete []token;
	token=getTokenNOOS(s,&type,pos);

	if (type==TOKEN_SYMBOL) {
		if (strcmp(token,":id")!=0) {
			delete []token;
			delete []variablename;
			delete []feature_variablename;
			return 0;
		} /* if */ 

		delete []token;
		token=getTokenNOOS(s,&type,pos);
		if (type==TOKEN_SYMBOL) {
			name=new Symbol(token);

			delete []token;
			token=getTokenNOOS(s,&type,pos);
			if (type!=TOKEN_RIGHT_PAR) {
				delete []token;
				delete name;
				delete []variablename;
				delete []feature_variablename;
				return 0;
			} /* if */ 
		} else {
			delete []token;
			delete []variablename;
			delete []feature_variablename;
			return 0;
		} /* if */ 

	} if (type==TOKEN_RIGHT_PAR) {
	} else {
		delete []token;
		delete []variablename;
		delete []feature_variablename;
		return 0;
	} /* if */ 

	// Create the empty FeatureTerm:
	if (name!=0) {
		FeatureTerm *found=0;

		found=m->SearchUndefinedFT(name);

		if (found!=0) {
			delete name;

			/* Delete it first, since it will be added again when returning from this function: */ 
			m->DeleteFT(found);
			f=found;
			f->setSort(sort);

		} else {
			if (sort==0) {
				f=FeatureTerm::SetFeatureTerm(name);
			} else {
				if (sort->get_data_type()==DATATYPE_SPECIAL) {
					f=new FeatureTerm(name,(SpecialTerm *)0,sort);
					f->m_ft->m_data_type=DATATYPE_FEATURETERM;	// temporarily make it a feture_term so that
																// the parser deals with it in an apropriate way					
					f->m_ft->m_value.m_ft.m_feature_name=new List<Symbol>;
					f->m_ft->m_value.m_ft.m_feature_value=new List<FeatureTerm>;
					specials->Add(f);
				} else {
					f=new FeatureTerm(name,sort,0);
				} // if 
			} /* if */ 
		} /* if */ 

	} else {
		if (sort==0) {
			f=FeatureTerm::SetFeatureTerm(name);
		} else {
			if (sort->get_data_type()==DATATYPE_SPECIAL) {
				f=new FeatureTerm(name,(SpecialTerm *)0,sort);
				f->m_ft->m_data_type=DATATYPE_FEATURETERM;	// temporarily make it a feture_term so that
															// the parser deals with it in an apropriate way					
				f->m_ft->m_value.m_ft.m_feature_name=new List<Symbol>;
				f->m_ft->m_value.m_ft.m_feature_value=new List<FeatureTerm>;
				specials->Add(f);
			} else {
				f=new FeatureTerm(name,sort,0);
			} // if 
		} /* if */ 
	} /* if */ 

	if (variable) {
		NOOSVariableRecord *nv;
//		printf("Adding variable \"%s\"\n",variablename);
		nv=new NOOSVariableRecord();
		nv->f=f;
		nv->variable=new Symbol(variablename);
		nvl->Add(nv);
	} /* if */ 

	delete []variablename;

	/* Features: */ 
	do{
		delete []token;
		token=getTokenNOOS(s,&type,pos);

		if (sort==0) {
			/* Set elements: */ 
			if (type==TOKEN_LEFT_PAR) {
				delete []token;
				token=getTokenNOOS(s,&type,pos);
				if (type==TOKEN_SYMBOL && strcmp(token,"define")==0) {
					hierarchy->Add(f);
					fvalue=fromStringNOOSInternal(s,m,o,vsort,pos,hierarchy,nprl,nvl,nvll,specials);
					hierarchy->Extract();
					if (fvalue==0) {
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} else if (type==TOKEN_ROOT) {
					NOOSPathRecord *npr=new NOOSPathRecord();
					if (hierarchy->EmptyP()) {
						npr->root=f;
					} else {
						npr->root=hierarchy->operator [](0);
					} /* if */ 
					npr->feature=0;
					npr->f=f;
					npr->p=new Path();

//					printf("ROOT: ");
					delete []token;
					token=getTokenNOOS(s,&type,pos);
					while(type==TOKEN_SYMBOL) {
						npr->p->Insert(new Symbol(token));
//						printf("%s ",token);
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} /* while */ 
//					printf("\n");
					if (type==TOKEN_RIGHT_PAR) {
						nprl->Add(npr);
						fvalue=0;
					} else {
						delete npr;
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} else if (type==TOKEN_PARENT) {
					int ndots=strlen(token);
					NOOSPathRecord *npr=new NOOSPathRecord();

					if (ndots==1) {
						npr->root=f;
					} else {
						if (hierarchy->EmptyP()) {
							delete npr;
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} else {
							int pos=hierarchy->Length()-(ndots-1);
							npr->root=hierarchy->operator [](pos);
						} /* if */ 
					} /* if */ 
					npr->feature=0;
					npr->f=f;
					npr->p=new Path();

//					printf("PARENT (%i): ",ndots);
					delete []token;
					token=getTokenNOOS(s,&type,pos);
					while(type==TOKEN_SYMBOL) {
						npr->p->Insert(new Symbol(token));
//						printf("%s ",token);
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} /* while */ 
//					printf("\n");
					if (type==TOKEN_RIGHT_PAR) {
						nprl->Add(npr);
						fvalue=0;
					} else {
						delete npr;
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} else {
					delete fname;
					delete []token;
					delete f;
					delete []feature_variablename;
					return 0;
				} /* if */ 	

			} else if (type==TOKEN_REF_VARIABLE) {
				NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
				nv->f=f;
				nv->feature=0;
				nv->variable=new Symbol(token);
				nvll->Add(nv);
//				printf("Added a variable reference to \"%s\" (to a SET)\n",token);
			} else if (type==TOKEN_SYMBOL) {
				FeatureTerm *f,*res=0;
				int num=0;
				List<FeatureTerm> *l;
				Symbol *n=new Symbol(token);

				l=m->SearchFT(n);

				l->Rewind();
				while(l->Iterate(f)) {
					if (vsort->inSort(f)) {
						res=f;
						num++;
					} /* if */ 
				} /* while */ 

				if (num==1) {
					fvalue=new FeatureTerm(res);
					delete n;
					while(!l->EmptyP()) l->ExtractIni();
					delete l;
				} else {
					if (num==0) {
						/* Create a new term of the appopiate sort and add it to the memory & undefined term list: */ 
						fvalue=new FeatureTerm(n,vsort,0);
						m->AddUndefinedFT(fvalue);
						fvalue=new FeatureTerm(fvalue);
						while(!l->EmptyP()) l->ExtractIni();
						delete l;								
					} else {
						while(!l->EmptyP()) l->ExtractIni();
						delete l;
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} /* if */ 

			} else if (type==3) {
				/* integer: */ 
				fvalue=new FeatureTerm((Symbol *)0,atoi(token),o);
			} else if (type==5) {
				/* float: */ 
				fvalue=new FeatureTerm((Symbol *)0,(float)atof(token),o);
			} else if (type==4) {
				/* symbol: */ 
				fvalue=new FeatureTerm((char *)0,token,o);
			} else if (type==1) {
				end=true;
			} else {
				delete fname;
				delete []token;
				delete f;
				delete []feature_variablename;
				return 0;
			} /* if */ 

			if (fvalue!=0) f->addSetValue(fvalue);
			fvalue=0;
		} else {

			// FEATURE TERM or SPECIAL TERM:
			bool delayed=false;

			if (type==TOKEN_LEFT_PAR) {
				/* Feature Name: */ 
				delete []token;
				token=getTokenNOOS(s,&type,pos);
				if (type!=2) {
					delete []token;
					delete f;
					return 0;
				} /* if */ 
				fname=new Symbol(token);

				/* Feature Value: */ 
				/* Feature Value: (may have several values to form a SET) */ 
				List<FeatureTerm> values_read;
				List<Symbol> variables_read;

				delete []token;
				token=getTokenNOOS(s,&type,pos);
			
				do{
					fvalue=0;
					if (type==TOKEN_LEFT_PAR) {
						if (feature_variable) {
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} // i 

						delete []token;
						token=getTokenNOOS(s,&type,pos);
						if (type==TOKEN_SYMBOL && strcmp(token,"define")==0) {
							hierarchy->Add(f);
							fvalue=fromStringNOOSInternal(s,m,o,sort->featureSort(fname),pos,hierarchy,nprl,nvl,nvll,specials);
							hierarchy->Extract();
							if (fvalue==0) {
								delete fname;
								delete []token;
								delete f;
								delete []feature_variablename;
								return 0;
							} /* if */ 
						} else if (type==TOKEN_ROOT) {
							NOOSPathRecord *npr=new NOOSPathRecord();
							if (hierarchy->EmptyP()) {
								npr->root=f;
							} else {
								npr->root=hierarchy->operator [](0);
							} /* if */ 
							npr->feature=new Symbol(fname);
							npr->f=f;
							npr->p=new Path();

							delete []token;
							token=getTokenNOOS(s,&type,pos);
							while(type==TOKEN_SYMBOL) {
								npr->p->Insert(new Symbol(token));
								delete []token;
								token=getTokenNOOS(s,&type,pos);
							} /* while */ 
							if (type==TOKEN_RIGHT_PAR) {
								nprl->Add(npr);
								delayed=true;
								fvalue=0;
							} else {
								delete npr;
								delete fname;
								delete []token;
								delete f;
								delete []feature_variablename;
								return 0;
							} /* if */ 
						} else if (type==TOKEN_PARENT) {
							int ndots=strlen(token);
							NOOSPathRecord *npr=new NOOSPathRecord();

							if (ndots==1) {
								npr->root=f;
							} else {
								if (hierarchy->EmptyP()) {
									delete npr;
									delete fname;
									delete []token;
									delete f;
									delete []feature_variablename;
									return 0;
								} else {
									int pos=hierarchy->Length()-(ndots-1);
									npr->root=hierarchy->operator [](pos);
								} /* if */ 
							} /* if */ 
							npr->feature=new Symbol(fname);;
							npr->f=f;
							npr->p=new Path();

							delete []token;
							token=getTokenNOOS(s,&type,pos);
							while(type==TOKEN_SYMBOL) {
								npr->p->Insert(new Symbol(token));
								delete []token;
								token=getTokenNOOS(s,&type,pos);
							} /* while */ 
							if (type==TOKEN_RIGHT_PAR) {
								nprl->Add(npr);
								delayed=true;
								fvalue=0;
							} else {
								delete npr;
								delete fname;
								delete []token;
								delete f;
								delete []feature_variablename;
								return 0;
							} /* if */ 
						
						} else {
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} /* if */ 	

						delete []token;
						token=getTokenNOOS(s,&type,pos);

					} else if (type==TOKEN_INIT_VARIABLE) {
						feature_variable=true;
						strcpy(feature_variablename,token);
						delete []token;
						token=getTokenNOOS(s,&type,pos);					
					} else if (type==TOKEN_REF_VARIABLE) {
						variables_read.Add(new Symbol(token));
//						printf("(1) Added a variable reference to \"%s\" (to the feature \"%s\")\n",token,fname->get());
						delayed=true;
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} else if (type==TOKEN_SYMBOL) {
						List<FeatureTerm> *l;
						Symbol *n=new Symbol(token);

						l=m->SearchFT(n);

						/* Filter those that are not of the apropriate sort: */ 
						{
							FeatureTerm *f=0,*res=0;
							int num=0;
							Sort *s;

							s=sort->featureSort(fname);

							l->Rewind();
							while(l->Iterate(f)) {
								if (s->inSort(f)) {
									res=f;
									num++;
								} /* if */ 
							} /* while */ 

							if (num==1) {
								fvalue=new FeatureTerm(res);
								delete n;
								while(!l->EmptyP()) l->ExtractIni();
								delete l;
							} else {
								if (num==0) {
									/* Create a new term of the appopiate sort and add it to the memory & undefined term list: */ 
									fvalue=new FeatureTerm(n,vsort,0);
									m->AddUndefinedFT(fvalue);
									fvalue=new FeatureTerm(fvalue);
									while(!l->EmptyP()) l->ExtractIni();
									delete l;								
								} else {
									delete n;
									while(!l->EmptyP()) l->ExtractIni();
									delete l;
									delete fname;
									delete []token;
									delete f;
									delete []feature_variablename;
									return 0;
								} /* if */ 
							} /* if */ 
						}

						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} else if (type==TOKEN_INTEGER) {
						/* integer: */ 
						fvalue=new FeatureTerm((Symbol *)0,atoi(token),o);
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} else if (type==TOKEN_FLOAT) {
						/* float: */ 
						fvalue=new FeatureTerm((Symbol *)0,(float)atof(token),o);
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} else if (type==TOKEN_STRING) {
						/* symbol: */ 
						fvalue=new FeatureTerm((char *)0,token,o);
						delete []token;
						token=getTokenNOOS(s,&type,pos);
					} else {
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 

					if (fvalue!=0) {
						if (feature_variable) {
							NOOSVariableRecord *nv;
//							printf("Adding variable \"%s\"\n",variablename);
							nv=new NOOSVariableRecord();
							nv->f=fvalue;
							nv->variable=new Symbol(feature_variablename);
							nvl->Add(nv);
							feature_variable=false;
						} // if
						values_read.Add(fvalue);
					} else {
						if (!delayed && !feature_variable) {
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} /* if */ 
					} /* if */ 

				}while(type!=TOKEN_RIGHT_PAR);

				/* Add read values to feature value: */ 
				if (values_read.Length()+variables_read.Length()==1) {
					if (values_read.Length()==1) {
						if (!f->defineFeatureValueSecure(fname,values_read.ExtractIni())) {
							printf("NOOS parser(4): wrong feature in sort! setting %s in %s\n",fname->get(),f->getSort()->get());
						} // if 
					} else {
						NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
						nv->f=f;
						nv->feature=new Symbol(fname);
						nv->variable=variables_read.ExtractIni();
						nvll->Add(nv);
//						printf("Added a variable link record to fature %s for variable %s\n",nv->feature->get(),nv->variable->get());
					} /* if */ 
				} else if (values_read.Length()+variables_read.Length()>1) {
					FeatureTerm *ft_tmp;

//					printf("Creating a set with %i+%i values\n",values_read.Length()+variables_read.Length());

					ft_tmp=FeatureTerm::SetFeatureTerm();
					if (!f->defineFeatureValueSecure(fname,ft_tmp)) {
						printf("NOOS parser(5): wrong feature in sort! setting %s in %s\n",fname->get(),f->getSort()->get());
					} // if 
					while(!values_read.EmptyP()) ft_tmp->addSetValue(values_read.ExtractIni());
					while(!variables_read.EmptyP()) {
						NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
						nv->f=ft_tmp;
						nv->feature=0;
						nv->variable=variables_read.ExtractIni();
						nvll->Add(nv);
//						printf("Added a variable link record to fature - for variable %s\n",nv->variable->get());
					} /* while */ 
				} /* if */ 
				delete fname;
		
			} else if (type==TOKEN_RIGHT_PAR) {
				end=true;
			} else {
				delete []token;
				delete f;
				delete []feature_variablename;
				return 0;
			} /* if */ 
		} /* if */ 
	}while(!end);

	delete []token;
	delete []feature_variablename;

	return f;
} /* FeatureTerm::fromStringNOOSInternal */ 


FeatureTerm *FeatureTerm::fromFileNOOS(FILE *fp,FTKBase *m,Ontology *o)
{
	int type=0;
	char *token=0;
	FeatureTerm *f;

	token=getTokenNOOS(fp,&type);
	if (type==TOKEN_LEFT_PAR) {
		delete []token;
		token=getTokenNOOS(fp,&type);
		if (type!=TOKEN_SYMBOL ||
			(strcmp(token,"define")!=0 &&
			strcmp(token,"define-episode")!=0)) {
			delete []token;
			return 0;
		} // if 
	} else if (type==TOKEN_SYMBOL) {
		FeatureTerm *res=0;
		int num=0;
		List<FeatureTerm> *l;
		Symbol *n=new Symbol(token);

		l=m->SearchFT(n);
		num=l->Length();

		if (num==1) {
			res=new FeatureTerm(l->operator[](0));
			delete n;
			while(!l->EmptyP()) l->ExtractIni();
			delete l;
		} else {
			while(!l->EmptyP()) l->ExtractIni();
			delete l;
			printf("NOOS Importer: Error 6: several objects share the same id '%s'\n",token);
			delete []token;
			return 0;
		} /* if */ 

	} else if (type==TOKEN_INTEGER) {
		/* integer: */ 
		return new FeatureTerm((Symbol *)0,atoi(token),o);
	} else if (type==TOKEN_FLOAT) {
		/* float: */ 
		return new FeatureTerm((Symbol *)0,(float)atof(token),o);
	} else if (type==TOKEN_STRING) {
		/* symbol: */ 
		return new FeatureTerm((char *)0,token,o);
	} else {
		delete []token;
		return 0;
	} // if 
	delete []token;

	{
		List<FeatureTerm> hierarchy;
		List<NOOSPathRecord> nprl;
		List<NOOSVariableRecord> nvl;
		List<NOOSVariableLinkRecord> nvll;
		List<FeatureTerm> specials;

		f=fromFileNOOSInternal(fp,m,o,o->get_sort("any"),&hierarchy,&nprl,&nvl,&nvll,&specials);

		if (f!=0) {
//			if (f->getName()!=0) printf("%s\n",f->getName()->get());

			/* process nprl list: */ 
			NOOSPathRecord *npr;
			List<FeatureTerm> *lf;
			FeatureTerm *f2;
			while(!nprl.EmptyP()) {
				npr=nprl.ExtractIni();
/*				
				{
					List<Symbol> l;
					Symbol *s;
					printf("NPR:\n");
					printf("path:\n");
					l.Instance(*(npr->p));
					l.Rewind();
					while(l.Iterate(s)) printf("%s \n",s->get());
					if (npr->feature!=0) printf("feature: %s\n",npr->feature->get());
									else printf("no feature\n");
					
				}
*/
				if (npr->root!=0 && npr->p!=0) {
					lf=npr->root->readPath(npr->p);
					if (lf!=0 && lf->Length()==1) {
						f2=lf->ExtractIni();
						delete lf;
						if (f2!=0 && npr->f!=0) {
							if (npr->feature==0 && npr->f->isSet()) {
								npr->f->addSetValue(new FeatureTerm(f2));
							} else if (npr->feature!=0 && npr->f->isFeatureTerm()) {
								FeatureTerm *f3;
								f3=npr->f->featureValue(npr->feature);
								if (f3!=0) {
									if (f3->isSet()) {
										f3->addSetValue(new FeatureTerm(f2));
										delete f3;
									} else {
										FeatureTerm *f4;
										f4=FeatureTerm::SetFeatureTerm();

										f4->addSetValue(f3);
										f4->addSetValue(new FeatureTerm(f2));
										npr->f->removeFeatureValue(npr->feature);
										if (!npr->f->defineFeatureValueSecure(npr->feature,f4)) {
											printf("NOOS parser(6): wrong feature in sort! setting %s in %s\n",npr->feature->get(),npr->f->getSort()->get());
										} // if 
									} /* if */ 
								} else {
									if (!npr->f->defineFeatureValueSecure(npr->feature,new FeatureTerm(f2))) {
										printf("NOOS parser(7): wrong feature in sort! setting %s in %s\n",npr->feature->get(),npr->f->getSort()->get());
									} // if 
								} /* if */ 
							} /* if */ 
						} /* if */ 	
						delete f2;
					} else {
						if (lf!=0) {
							delete lf;
						} /* if */ 
					} /* if */ 
				} /* if */ 
				delete npr;
			} /* while */ 

			/* process nvll: */ 
			NOOSVariableRecord *vr,*vrtmp;
			NOOSVariableLinkRecord *vl;
			while(!nvll.EmptyP()) {
				vl=nvll.ExtractIni();
				if (vl->f!=0 && vl->variable!=0) {
					vr=0;
					nvl.Rewind();
					while(vr==0 && nvl.Iterate(vrtmp)) {
						if (vrtmp->variable->cmp(vl->variable)) vr=vrtmp;
					} /* while */ 

					if (vr!=0) {
						if (vl->feature==0 && vl->f->isSet()) {
							vl->f->addSetValue(new FeatureTerm(vr->f));
						} else if (vl->feature!=0 && vl->f->isFeatureTerm()) {
							if (!vl->f->defineFeatureValueSecure(vl->feature,new FeatureTerm(vr->f))) {
								printf("NOOS parser(8): wrong feature in sort! setting %s in %s\n",vl->feature->get(),vl->f->getSort()->get());
							} // if 
						} else {
							printf("Variable: %s\n",vl->variable->get());
							printf("failure!\n");
							printf("Variable->f: %s, Variable->feature: %s\n",vl->f->getSort()->get(),vl->feature->get());
						} /* if */ 
					} /* if */ 
				} /* if */ 
				delete vl;
			} /* while */ 

			/* process specials: */ 
			{
				List<Symbol> names;
				List<FeatureTerm> values;
				FeatureTerm *f_s;

				while(!specials.EmptyP()) {
					f_s=specials.ExtractIni();
				
					while(!f_s->m_ft->m_value.m_ft.m_feature_name->EmptyP()) names.Add(f_s->m_ft->m_value.m_ft.m_feature_name->ExtractIni());
					while(!f_s->m_ft->m_value.m_ft.m_feature_value->EmptyP()) values.Add(f_s->m_ft->m_value.m_ft.m_feature_value->ExtractIni());
					delete f_s->m_ft->m_value.m_ft.m_feature_name;
					delete f_s->m_ft->m_value.m_ft.m_feature_value;
					f_s->m_ft->m_value.m_ft.m_feature_name=0;
					f_s->m_ft->m_value.m_ft.m_feature_value=0;

					f_s->m_ft->m_value.m_special=f_s->getSort()->createSpecial(&names,&values);
					f_s->m_ft->m_data_type=DATATYPE_SPECIAL;
				} // while 
			}
			
		} /* if */ 

		return f;
	}
} /* FeatureTerm::fromFileNOOS */ 
 

/*
#define TOKEN_LEFT_PAR		0
#define TOKEN_RIGHT_PAR		1
#define TOKEN_SYMBOL		2
#define TOKEN_INTEGER		3
#define TOKEN_STRING		4
#define TOKEN_FLOAT			5
#define TOKEN_ROOT			6
#define TOKEN_PREVIOUS		7
#define TOKEN_INIT_VARIABLE	8
#define TOKEN_REF_VARIABLE	9
*/

FeatureTerm *FeatureTerm::fromFileNOOSInternal(FILE *fp,FTKBase *m,Ontology *o,Sort *vsort,List<FeatureTerm> *hierarchy,List<NOOSPathRecord> *nprl,List<NOOSVariableRecord> *nvl,List<NOOSVariableLinkRecord> *nvll,List<FeatureTerm> *specials)
{
	char *token=0;
	int type=0;
	Sort *sort=0;
	Symbol *name=0;
	Symbol *fname=0;
	FeatureTerm *fvalue=0;
	bool end=false;
	FeatureTerm *f=0;
	bool variable=false;
	char *variablename;
	bool feature_variable=false;
	char *feature_variablename;

	variablename=new char[256];
	feature_variablename=new char[256];

	/* Sort and name: */ 
	token=getTokenNOOS(fp,&type);
	variable=false;

//	printf("%i %s\n",type,token);

	if (type==TOKEN_INIT_VARIABLE) {
		variable=true;
		strcpy(variablename,token);
		delete []token;
		token=getTokenNOOS(fp,&type);
	} /* if */ 

	if (type!=TOKEN_LEFT_PAR) {
		delete []variablename;
		delete []feature_variablename;
		return 0;
	} /* if */ 

	delete []token;
	token=getTokenNOOS(fp,&type);
	if (type!=TOKEN_SYMBOL) {
		delete []variablename;
		delete []variablename;
		return 0;
	} /* if */ 
	if (strcmp(token,"set")==0) {
		sort=0;
	} else {
		sort=o->get_sort(token);
	} /* if */ 
	delete []token;
	token=getTokenNOOS(fp,&type);

	if (type==TOKEN_SYMBOL) {
		if (strcmp(token,":id")!=0) {
			delete []token;
			delete []variablename;
			delete []variablename;
			return 0;
		} /* if */ 

		delete []token;
		token=getTokenNOOS(fp,&type);
		if (type==TOKEN_SYMBOL) {
			name=new Symbol(token);

			delete []token;
			token=getTokenNOOS(fp,&type);
			if (type!=TOKEN_RIGHT_PAR) {
				delete []token;
				delete name;
				delete []variablename;
				delete []variablename;
				return 0;
			} /* if */ 
		} else {
			delete []token;
			delete []variablename;
			delete []variablename;
			return 0;
		} /* if */ 

	} if (type==TOKEN_RIGHT_PAR) {
	} else {
		delete []token;
		delete []variablename;
		delete []variablename;
		return 0;
	} /* if */ 

	/* Check if there is some undefined term with the appropiate name, use it and remove it from the undefined term list: */ 
	if (name!=0) {
		FeatureTerm *found=0;

		found=m->SearchUndefinedFT(name);

		if (found!=0) {
			delete name;

			/* Delete it first, since it will be added again when returning from this function: */ 
			m->DeleteFT(found);
			f=found;
			f->setSort(sort);

		} else {
			if (sort==0) {
				f=FeatureTerm::SetFeatureTerm(name);
			} else {
				if (sort->get_data_type()==DATATYPE_SPECIAL) {
					f=new FeatureTerm(name,(SpecialTerm *)0,sort);
					f->m_ft->m_data_type=DATATYPE_FEATURETERM;	// temporarily make it a feture_term so that
																// the parser deals with it in an apropriate way					
					f->m_ft->m_value.m_ft.m_feature_name=new List<Symbol>;
					f->m_ft->m_value.m_ft.m_feature_value=new List<FeatureTerm>;
					specials->Add(f);
				} else {
					f=new FeatureTerm(name,sort,0);
				} // if 
			} /* if */ 
		} /* if */ 

	} else {
		if (sort==0) {
			f=FeatureTerm::SetFeatureTerm(name);
		} else {
			if (sort->get_data_type()==DATATYPE_SPECIAL) {
				f=new FeatureTerm(name,(SpecialTerm *)0,sort);
				f->m_ft->m_data_type=DATATYPE_FEATURETERM;	// temporarily make it a feture_term so that
															// the parser deals with it in an apropriate way					
				f->m_ft->m_value.m_ft.m_feature_name=new List<Symbol>;
				f->m_ft->m_value.m_ft.m_feature_value=new List<FeatureTerm>;
				specials->Add(f);
			} else {
				f=new FeatureTerm(name,sort,0);
			} // if 
		} /* if */ 
	} /* if */ 

	if (variable) {
		NOOSVariableRecord *nv;
//		printf("Adding variable \"%s\"\n",variablename);
		nv=new NOOSVariableRecord();
		nv->f=f;
		nv->variable=new Symbol(variablename);
		nvl->Add(nv);
	} /* if */ 

	delete []variablename;

	/* Features: */ 
	do{
		delete []token;
		token=getTokenNOOS(fp,&type);

		if (sort==0) {
			/* Set elements: */ 
			if (type==TOKEN_LEFT_PAR) {
				delete []token;
				token=getTokenNOOS(fp,&type);
				if (type==TOKEN_SYMBOL && strcmp(token,"define")==0) {
					hierarchy->Add(f);
					fvalue=fromFileNOOSInternal(fp,m,o,vsort,hierarchy,nprl,nvl,nvll,specials);
					hierarchy->Extract();
					if (fvalue==0) {
						delete fname;
						delete []token;
						delete f;
						printf("NOOS Importer: Error 1: cannot parse the first element of a set!\n");
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} else if (type==TOKEN_ROOT) {
					NOOSPathRecord *npr=new NOOSPathRecord();
					if (hierarchy->EmptyP()) {
						npr->root=f;
					} else {
						npr->root=hierarchy->operator [](0);
					} /* if */ 
					npr->feature=0;
					npr->f=f;
					npr->p=new Path();

//					printf("ROOT: ");
					delete []token;
					token=getTokenNOOS(fp,&type);
					while(type==TOKEN_SYMBOL) {
						npr->p->Insert(new Symbol(token));
//						printf("%s ",token);
						token=getTokenNOOS(fp,&type);
					} /* while */ 
//					printf("\n");
					if (type==TOKEN_RIGHT_PAR) {
						nprl->Add(npr);
						fvalue=0;
					} else {
						delete fname;
						delete []token;
						delete f;
						printf("NOOS Importer: Error 2\n");
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} else if (type==TOKEN_PARENT) {
					int ndots=strlen(token);
					NOOSPathRecord *npr=new NOOSPathRecord();

					if (ndots==1) {
						npr->root=f;
					} else {
						if (hierarchy->EmptyP()) {
							delete npr;
							delete fname;
							delete []token;
							delete f;
							printf("NOOS Importer: Error 3\n");
							delete []feature_variablename;
							return 0;
						} else {
							int pos=hierarchy->Length()-(ndots-1);
							npr->root=hierarchy->operator [](pos);
						} /* if */ 
					} /* if */ 
					npr->feature=0;
					npr->f=f;
					npr->p=new Path();

//					printf("PARENT (%i): ",ndots);
					delete []token;
					token=getTokenNOOS(fp,&type);
					while(type==TOKEN_SYMBOL) {
						npr->p->Insert(new Symbol(token));
//						printf("%s ",token);
						token=getTokenNOOS(fp,&type);
					} /* while */ 
//					printf("\n");
					if (type==TOKEN_RIGHT_PAR) {
						nprl->Add(npr);
						fvalue=0;
					} else {
						delete npr;
						delete fname;
						delete []token;
						delete f;
						printf("NOOS Importer: Error 4\n");
						delete []feature_variablename;
						return 0;
					} /* if */ 

				} else {
					delete fname;
					delete []token;
					delete f;
					printf("NOOS Importer: Error 5\n");
					delete []feature_variablename;
					return 0;
				} /* if */ 				

			} else if (type==TOKEN_REF_VARIABLE) {
				NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
				nv->f=f;
				nv->feature=0;
				nv->variable=new Symbol(token);
				nvll->Add(nv);
				printf("Added a variable reference to \"%s\" (to a SET)\n",token);
			} else if (type==TOKEN_SYMBOL) {
				FeatureTerm *f,*res=0;
				int num=0;
				List<FeatureTerm> *l;
				Symbol *n=new Symbol(token);

				l=m->SearchFT(n);

				l->Rewind();
				while(l->Iterate(f)) {
					if (vsort->inSort(f)) {
						res=f;
						num++;
					} /* if */ 
				} /* while */ 

				if (num==1) {
					fvalue=new FeatureTerm(res);
					delete n;
					while(!l->EmptyP()) l->ExtractIni();
					delete l;
				} else {
					if (num==0) {
						/* Create a new term of the appopiate sort and add it to the memory & undefined term list: */ 
						fvalue=new FeatureTerm(n,vsort,0);
						m->AddUndefinedFT(fvalue);
						fvalue=new FeatureTerm(fvalue);
						while(!l->EmptyP()) l->ExtractIni();
						delete l;								
					} else {
						while(!l->EmptyP()) l->ExtractIni();
						delete l;
						delete fname;
						delete []token;
						delete f;
						printf("NOOS Importer: Error 6\n");
						delete []feature_variablename;
						return 0;
					} /* if */ 
				} /* if */ 

			} else if (type==TOKEN_INTEGER) {
				/* integer: */ 
				fvalue=new FeatureTerm((Symbol *)0,atoi(token),o);
			} else if (type==TOKEN_FLOAT) {
				/* float: */ 
				fvalue=new FeatureTerm((Symbol *)0,(float)atof(token),o);
			} else if (type==TOKEN_STRING) {
				/* symbol: */ 
				fvalue=new FeatureTerm((char *)0,token,o);
			} else if (type==1) {
				end=true;
			} else {
				delete fname;
				delete []token;
				delete f;
				printf("NOOS Importer: Error 7\n");
				delete []feature_variablename;
				return 0;
			} /* if */ 

			if (fvalue!=0) f->addSetValue(fvalue);
			fvalue=0;
		} else {
			bool delayed=false;


			if (type==TOKEN_LEFT_PAR) {
				/* Feature Name: */ 
				delete []token;
				token=getTokenNOOS(fp,&type);
				if (type!=TOKEN_SYMBOL) {
					delete []token;
					delete f;
					printf("NOOS Importer: Error 8\n");
					delete []feature_variablename;
					return 0;
				} /* if */ 
				if (strcmp(token,"define")==0) {
					delete []token;
					delete f;
					printf("NOOS Importer: Error 8a\n");
					delete []feature_variablename;
					return 0;
				} /* if */ 
				fname=new Symbol(token);

				/* Feature Value: (may have several values to form a SET) */ 
				List<FeatureTerm> values_read;
				List<Symbol> variables_read;

				delete []token;
				token=getTokenNOOS(fp,&type);				
				
				do{
					fvalue=0;
					if (type==TOKEN_LEFT_PAR) {
						if (feature_variable) {
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} // i 

						delete []token;
						token=getTokenNOOS(fp,&type);
						if (type==TOKEN_SYMBOL && strcmp(token,"define")==0) {
							hierarchy->Add(f);
							fvalue=fromFileNOOSInternal(fp,m,o,sort->featureSort(fname),hierarchy,nprl,nvl,nvll,specials);
							hierarchy->Extract();
							if (fvalue==0) {
								printf("NOOS Importer: Error 9 (token: %s): cannot parse the value of a feature\n",token);
								delete fname;
								delete []token;
								delete f;
								delete []feature_variablename;
								return 0;
							} /* if */ 
						} else if (type==TOKEN_ROOT) {
							NOOSPathRecord *npr=new NOOSPathRecord();
							if (hierarchy->EmptyP()) {
								npr->root=f;
							} else {
								npr->root=hierarchy->operator [](0);
							} /* if */ 
							npr->feature=new Symbol(fname);
							npr->f=f;
							npr->p=new Path();

							delete []token;
							token=getTokenNOOS(fp,&type);
							while(type==TOKEN_SYMBOL) {
								npr->p->Insert(new Symbol(token));
								delete []token;
								token=getTokenNOOS(fp,&type);
							} /* while */ 
							if (type==TOKEN_RIGHT_PAR) {
								nprl->Add(npr);
								delayed=true;
								fvalue=0;
							} else {
								delete npr;
								delete fname;
								delete []token;
								delete f;
								printf("NOOS Importer: Error 10\n");
								delete []feature_variablename;
								return 0;
							} /* if */ 
						} else if (type==TOKEN_PARENT) {
							int ndots=strlen(token);
							NOOSPathRecord *npr=new NOOSPathRecord();

							if (ndots==1) {
								npr->root=f;
							} else {
								if (hierarchy->EmptyP()) {
									delete npr;
									delete fname;
									delete []token;
									delete f;
									printf("NOOS Importer: Error 11\n");
									delete []feature_variablename;
									return 0;
								} else {
									int pos=hierarchy->Length()-(ndots-1);
									npr->root=hierarchy->operator [](pos);
								} /* if */ 
							} /* if */ 
							npr->feature=new Symbol(fname);
							npr->f=f;
							npr->p=new Path();

							delete []token;
							token=getTokenNOOS(fp,&type);
							while(type==TOKEN_SYMBOL) {
								npr->p->Insert(new Symbol(token));
								delete []token;
								token=getTokenNOOS(fp,&type);
							} /* while */ 
							if (type==TOKEN_RIGHT_PAR) {
								nprl->Add(npr);
								delayed=true;
								fvalue=0;
							} else {
								delete npr;
								delete fname;
								delete []token;
								delete f;
								printf("NOOS Importer: Error 12\n");
								delete []feature_variablename;
								return 0;
							} /* if */ 
						
						} else {
							printf("NOOS Importer: Error 13. Expected [SYMBOL|ROOM|PARENT] and found %i -> %s\n",type,token);
							delete fname;
							delete []token;
							delete f;
							delete []feature_variablename;
							return 0;
						} /* if */ 	

						delete []token;
						token=getTokenNOOS(fp,&type);
					
					} else if (type==TOKEN_INIT_VARIABLE) {
						feature_variable=true;
						strcpy(feature_variablename,token);
						delete []token;
						token=getTokenNOOS(fp,&type);

					} else if (type==TOKEN_REF_VARIABLE) {
						variables_read.Add(new Symbol(token));
//						printf("(2) Added a variable reference to \"%s\" (to the feature \"%s\")\n",token,fname->get());
						delayed=true;
						delete []token;
						token=getTokenNOOS(fp,&type);
					} else if (type==TOKEN_SYMBOL) {
						List<FeatureTerm> *l;
						Symbol *n=new Symbol(token);

						l=m->SearchFT(n);

						/* Filter those that are not of the apropriate sort: */ 
						{
							FeatureTerm *f=0,*res=0;
							int num=0;
							Sort *s;

							s=sort->featureSort(fname);
							if (s==0) {
								printf("NOOS Importer: Error 18, possible incorrect feature name '%s'\n",fname->get());
								delete []feature_variablename;
								return 0;
							} /* if */ 

							l->Rewind();
							while(l->Iterate(f)) {
								if (s->inSort(f)) {
									res=f;
									num++;
								} /* if */ 
							} /* while */ 

							if (num==1) {
								fvalue=new FeatureTerm(res);
								delete n;
								while(!l->EmptyP()) l->ExtractIni();
								delete l;
							} else {
								if (num==0) {
									/* Create a new term of the appopiate sort and add it to the memory & undefined term list: */ 
									fvalue=new FeatureTerm(n,s,0);
									m->AddUndefinedFT(fvalue);
									fvalue=new FeatureTerm(fvalue);
									while(!l->EmptyP()) l->ExtractIni();
									delete l;								
								} else {
									delete n;
									while(!l->EmptyP()) l->ExtractIni();
									delete l;
									delete fname;
									delete []token;
									delete f;
									printf("NOOS Importer: Error 14\n");
									delete []feature_variablename;
									return 0;
								} /* if */ 
							} /* if */ 
						}

						delete []token;
						token=getTokenNOOS(fp,&type);
					} else if (type==TOKEN_INTEGER) {
						/* integer: */ 
						fvalue=new FeatureTerm((Symbol *)0,atoi(token),o);
						delete []token;
						token=getTokenNOOS(fp,&type);
					} else if (type==TOKEN_FLOAT) {
						/* float: */ 
						fvalue=new FeatureTerm((Symbol *)0,(float)atof(token),o);
						delete []token;
						token=getTokenNOOS(fp,&type);
					} else if (type==TOKEN_STRING) {
						/* symbol: */ 
						fvalue=new FeatureTerm((char *)0,token,o);
						delete []token;
						token=getTokenNOOS(fp,&type);
					} else {
						printf("NOOS Importer: Error 15 (token: %i - %s)\n",type,token);
						delete fname;
						delete []token;
						delete f;
						delete []feature_variablename;
						return 0;
					} /* if */ 

					if (fvalue!=0) {
						if (feature_variable) {
							NOOSVariableRecord *nv;
//							printf("Adding variable \"%s\"\n",variablename);
							nv=new NOOSVariableRecord();
							nv->f=fvalue;
							nv->variable=new Symbol(feature_variablename);
							nvl->Add(nv);
							feature_variable=false;
						} // if
						values_read.Add(fvalue);
					} else {
						if (!delayed && !feature_variable) {
							delete fname;
							delete []token;
							delete f;
							printf("NOOS Importer: Error 16\n");
							delete []feature_variablename;
							return 0;
						} /* if */ 
					} /* if */ 

				}while(type!=TOKEN_RIGHT_PAR);

				/* Add read values to feature value: */ 
				if (values_read.Length()+variables_read.Length()==1) {
					if (values_read.Length()==1) {
						FeatureTerm *f2;
						f2=values_read.ExtractIni();
						if (!f->defineFeatureValueSecure(fname,f2)) {
							printf("NOOS parser(9): wrong feature in sort! setting %s in %s\n",fname->get(),f->getSort()->get());
						} // if 
					} else {
						NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
						nv->f=f;
						nv->feature=new Symbol(fname);
						nv->variable=variables_read.ExtractIni();
						nvll->Add(nv);
//						printf("Added a variable link record to fature %s for variable %s\n",nv->feature->get(),nv->variable->get());
					} /* if */ 
				} else if (values_read.Length()+variables_read.Length()>1) {
					FeatureTerm *ft_tmp;

//					printf("(2) Creating a set with %i+%i values\n",values_read.Length(),variables_read.Length());

					ft_tmp=FeatureTerm::SetFeatureTerm();
					if (!f->defineFeatureValueSecure(fname,ft_tmp)) {
						printf("NOOS parser(10): wrong feature in sort! setting %s in %s\n",fname->get(),f->getSort()->get());
					} // if 
					while(!values_read.EmptyP()) ft_tmp->addSetValue(values_read.ExtractIni());
					
					while(!variables_read.EmptyP()) {						
						NOOSVariableLinkRecord *nv=new NOOSVariableLinkRecord();
						nv->f=ft_tmp;
						nv->feature=0;
						nv->variable=variables_read.ExtractIni();
						nvll->Add(nv);			
//						printf("Added a variable link record to fature - for variable %s\n",nv->variable->get());
					} // while 
					
				} /* if */ 
				delete fname;
					
			} else if (type==TOKEN_RIGHT_PAR) {
				end=true;
			} else {
				delete []token;
				delete f;
				printf("NOOS Importer: Error 17\n");
				delete []feature_variablename;
				return 0;
			} /* if */ 
		} /* if */ 
	}while(!end);

	delete []token;
	delete []feature_variablename;

	return f;
} /* FeatureTerm::ImportDefineNOOS */ 



/* 
	type:
	0 = (
	1 = )
	2 = symbol
	3 = integer
	4 = string
	5 = float
*/
char *FeatureTerm::getTokenNOOS(FILE *fp,int *type)
{
	char tmp[256],*token;
	int i=0;
	char c;
	bool end=false;
	int state;

	*type=-1;

	state=0;

	while(!end) {
		c=fgetc(fp);

		if (!feof(fp)) {
			switch(state) {
			case -2: /* block comment: */ 
				if (c=='|') {
					c=fgetc(fp);
					if (c=='#') state=0;
				} /* if */ 
				break;
			case -1: /* comment */ 
				if (c=='\r' || c=='\n') state=0;
				break;
			case 0:
				if (c==';') {
					state=-1;
				} else if (c=='#') {
					c=fgetc(fp);
					if (c=='|') {
						state=-2;
					} else {
						*type=-1;
						return 0;
					} /* if */ 
				} else if (c=='>') {
					tmp[i++]=c;
					c=fgetc(fp);
					if (c=='>') {
						tmp[i++]=c;
						*type=TOKEN_ROOT;
					} /* if */ 
					end=true;
				} else if (c=='.') {
					*type=TOKEN_PARENT;
					tmp[i++]=c;
					do {
						c=fgetc(fp);
						if (c=='.') tmp[i++]=c;
					}while(c=='.');
					ungetc(c,fp);
					end=true;
				} else if (c=='?') {
					*type=TOKEN_INIT_VARIABLE;
					state=4;				
				} else if (c=='!') {
					*type=TOKEN_REF_VARIABLE;
					state=4;									
				} else if (c=='(' || c==')') {
					tmp[i++]=c;
					if (c=='(') *type=TOKEN_LEFT_PAR;
						   else *type=TOKEN_RIGHT_PAR;
					end=true;
				} else if (c=='\"') {
					state=3;
				} else if ((c>='0' && c<='9') || c=='-') {
					*type=TOKEN_INTEGER;
					tmp[i++]=c;
					state=2;
				} else if (c!=' ' && c!='\r' && c!='\n' && c!='\t') {
					tmp[i++]=c;
					state=1;
				} /* if */ 
				break;
			case 1:
				if (c!=' ' && c!='\r' && c!='\n' && c!='\t' && 
					c!='(' && c!=')' && c!='\"') {
					tmp[i++]=c;
				} else {
					ungetc(c,fp);
					*type=TOKEN_SYMBOL;
					end=true;
				} /* if */ 
				break;
			case 2:
				if ((c>='0' && c<='9') || c=='.') {
					tmp[i++]=c;
					if (c=='.') *type=TOKEN_FLOAT;
				} else {
					ungetc(c,fp);
					end=true;
				} /* if */ 
				break;
			case 3:
				if (c!='\"') {
					tmp[i++]=c;
				} else {
					*type=TOKEN_STRING;
					end=true;
				} /* if */ 
				break;
			case 4:
				if (c!=' ' && c!='\r' && c!='\n' && c!='\t' && 
					c!='(' && c!=')' && c!='\"') {
					tmp[i++]=c;
				} else {
					ungetc(c,fp);
					end=true;
				} /* if */ 
				break;
			} /* switch */ 
		} else {
			end=true;
		} /* if */ 
	} /* while */ 

	tmp[i]=0;
	if (strlen(tmp)==0 && *type!=4) {
		if (*type==TOKEN_REF_VARIABLE) {
			*type=TOKEN_SINGLETON;
			return 0;
		} else {
			*type=-1;
			return 0;
		} // if 
	} /* if */ 

	token=new char[strlen(tmp)+1];
	strcpy(token,tmp);
	if (*type!=TOKEN_STRING) strlwr(token);

//	printf("token: %i - %s\n",*type,token);

	return token;
} /* FeatureTerm::getTokenNOOS */ 

